package demo.guiJFrame;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Game2048_v1 {
	JFrame frame;
	JPanel panel;
	JButton button;
	Grid[] grids;
	int[][] num;
	boolean ifMoveRight = true, ifMoveLeft = true, ifMoveUp = true, ifMoveDown = true;

	public Game2048_v1() {
		setNum();
		frame = new JFrame("WEY2048");
		frame.setBounds(750, 300, 400, 430);
		frame.setLayout(new BorderLayout());
		panel = new JPanel();
		panel.setSize(400, 400);
		panel.setLayout(new GridLayout(4, 4, 1, 1));
		grids = new Grid[16];
		for (int i = 0; i < 16; i++) {
			grids[i] = new Grid(num[i / 4][i % 4]);
			panel.add(grids[i].ret());
		}
		button = new JButton("����Ϸ");
		addLis();
		frame.add(button, BorderLayout.NORTH);
		frame.add(panel, BorderLayout.CENTER);
		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		panel.requestFocus();
	}

	private void addLis() {
		button.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				setNum();
				flush();
				panel.requestFocus();
			}
		});
		panel.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (ifFull()) {
					JOptionPane.showMessageDialog(frame, "���Ѿ���·����");
					return;
				}
				int i = e.getKeyCode();
				boolean isMove = false;
				if (i == KeyEvent.VK_UP)
					isMove = gridUp();
				else if (i == KeyEvent.VK_DOWN)
					isMove = gridDown();
				else if (i == KeyEvent.VK_LEFT)
					isMove = gridLeft();
				else if (i == KeyEvent.VK_RIGHT)
					isMove = gridRight();
				flush();
				if (isMove) {
					addNum();
					flush();
				}
			}

			private boolean gridRight() {
				if (!ifMoveRight)
					return false;
				for (int i = 0; i < 4; i++) {
					for (int x = 0; x < 4; x++) {
						for (int j = 3; j > 0; j--) {
							if (num[i][j] == 0) {
								num[i][j] = num[i][j - 1];
								num[i][j - 1] = 0;
							}
						}
					}
					for (int j = 3; j > 0; j--) {
						if (num[i][j] == num[i][j - 1]) {
							num[i][j] = num[i][j] * 2;
							num[i][j - 1] = 0;
						}
					}
					for (int x = 0; x < 4; x++) {
						for (int j = 3; j > 0; j--) {
							if (num[i][j] == 0) {
								num[i][j] = num[i][j - 1];
								num[i][j - 1] = 0;
							}
						}
					}
				}
				return true;
			}

			private boolean gridLeft() {
				if (!ifMoveLeft)
					return false;
				for (int i = 0; i < 4; i++) {
					for (int x = 0; x < 4; x++) {
						for (int j = 0; j < 3; j++) {
							if (num[i][j] == 0) {
								num[i][j] = num[i][j + 1];
								num[i][j + 1] = 0;
							}
						}
					}
					for (int j = 0; j < 3; j++) {
						if (num[i][j] == num[i][j + 1]) {
							num[i][j] = num[i][j] * 2;
							num[i][j + 1] = 0;
						}
					}
					for (int x = 0; x < 4; x++) {
						for (int j = 0; j < 3; j++) {
							if (num[i][j] == 0) {
								num[i][j] = num[i][j + 1];
								num[i][j + 1] = 0;
							}
						}
					}
				}
				return true;
			}

			private boolean gridDown() {
				if (!ifMoveDown)
					return false;
				for (int j = 0; j < 4; j++) {
					for (int x = 0; x < 4; x++) {
						for (int i = 3; i > 0; i--) {
							if (num[i][j] == 0) {
								num[i][j] = num[i - 1][j];
								num[i - 1][j] = 0;
							}
						}
					}
					for (int i = 3; i > 0; i--) {
						if (num[i][j] == num[i - 1][j]) {
							num[i][j] = num[i][j] * 2;
							num[i - 1][j] = 0;
						}
					}
					for (int x = 0; x < 4; x++) {
						for (int i = 3; i > 0; i--) {
							if (num[i][j] == 0) {
								num[i][j] = num[i - 1][j];
								num[i - 1][j] = 0;
							}
						}
					}
				}
				return true;
			}

			private boolean gridUp() {
				if (!ifMoveUp)
					return false;
				for (int j = 0; j < 4; j++) {
					for (int x = 0; x < 4; x++) {
						for (int i = 0; i < 3; i++) {
							if (num[i][j] == 0) {
								num[i][j] = num[i + 1][j];
								num[i + 1][j] = 0;
							}
						}
					}
					for (int i = 0; i < 3; i++) {
						if (num[i][j] == num[i + 1][j]) {
							num[i][j] = num[i][j] * 2;
							num[i + 1][j] = 0;
						}
					}
					for (int x = 0; x < 4; x++) {
						for (int i = 0; i < 3; i++) {
							if (num[i][j] == 0) {
								num[i][j] = num[i + 1][j];
								num[i + 1][j] = 0;
							}
						}
					}
				}
				return true;
			}
		});
	}

	private void flush() {
		for (int i = 0; i < 16; i++) {
			grids[i].update(num[i / 4][i % 4]);
		}
	}

	private void setNum() {
		num = new int[4][4];
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++)
				num[i][j] = 0;
		for (int i = 0; i < 5; i++)
			addNum();
	}

	private void addNum() {
		int m = (int) (Math.random() * 4);
		int n = (int) (Math.random() * 4);
		while (num[m][n] != 0) {
			m = (int) (Math.random() * 4);
			n = (int) (Math.random() * 4);
		}
		num[m][n] = 2;
	}

	private boolean ifFull() {
		ifMoveRight = false;
		for (int i = 0; i < 4; i++)
			for (int j = 3; j > 0; j--)
				if ((num[i][j] == 0 && num[i][j - 1] != 0) || (num[i][j] == num[i][j - 1] && num[i][j] != 0))
					ifMoveRight = true;
		ifMoveLeft = false;
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 3; j++)
				if ((num[i][j] == 0 && num[i][j + 1] != 0) || (num[i][j] == num[i][j + 1]) && num[i][j] != 0)
					ifMoveLeft = true;
		ifMoveDown = false;
		for (int j = 0; j < 4; j++)
			for (int i = 3; i > 0; i--)
				if ((num[i][j] == 0 && num[i - 1][j] != 0) || (num[i][j] == num[i - 1][j] && num[i][j] != 0))
					ifMoveDown = true;
		ifMoveUp = false;
		for (int j = 0; j < 4; j++)
			for (int i = 0; i < 3; i++)
				if ((num[i][j] == 0 && num[i + 1][j] != 0) || (num[i][j] == num[i + 1][j] && num[i][j] != 0))
					ifMoveUp = true;
		return !(ifMoveRight || ifMoveLeft || ifMoveDown || ifMoveUp);
	}

	public static void main(String[] args) {
		new Game2048_v1();
	}
}

class Grid {
	JLabel lab;

	public Grid(int num) {
		lab = new JLabel();
		lab.setHorizontalAlignment(JLabel.CENTER);
		lab.setFont(new Font("����", Font.BOLD, 20));
		lab.setOpaque(true);
		set(num);
	}

	private void set(int num) {
		String str = num + "";
		if (num == 0)
			str = "";
		lab.setText(str);
		switch (num) {
		case 2:
			lab.setBackground(new Color(238, 228, 218));
			break;
		case 4:
			lab.setBackground(new Color(237, 224, 200));
			break;
		case 8:
			lab.setBackground(new Color(242, 177, 121));
			break;
		case 16:
			lab.setBackground(new Color(245, 149, 99));
			break;
		case 32:
			lab.setBackground(new Color(246, 124, 95));
			break;
		case 64:
			lab.setBackground(new Color(246, 94, 59));
			break;
		case 128:
			lab.setBackground(new Color(237, 207, 114));
			break;
		case 256:
			lab.setBackground(new Color(237, 204, 97));
			break;
		case 512:
			lab.setBackground(new Color(237, 200, 80));
			break;
		case 1024:
			lab.setBackground(new Color(237, 197, 63));
			break;
		case 2048:
			lab.setBackground(new Color(237, 194, 46));
			break;
		default:
			lab.setBackground(Color.WHITE);
		}
	}

	public void update(int num) {
		set(num);
	}

	public JLabel ret() {
		return lab;
	}
}
